package com.mini.mybatis.mybatisministep06.sqlsession.configuration;

import com.mini.mybatis.mybatisministep06.binding.MapperRegistry;
import com.mini.mybatis.mybatisministep06.datasource.durid.DruidDataSourceFactory;
import com.mini.mybatis.mybatisministep06.datasource.pooled.PooledDataSourceFactory;
import com.mini.mybatis.mybatisministep06.datasource.unpooled.UnPooledDataSourceFactory;
import com.mini.mybatis.mybatisministep06.executor.Executor;
import com.mini.mybatis.mybatisministep06.executor.SimpleExecutor;
import com.mini.mybatis.mybatisministep06.executor.resultset.DefaultResultSetHandler;
import com.mini.mybatis.mybatisministep06.executor.resultset.ResultSetHandler;
import com.mini.mybatis.mybatisministep06.executor.statement.PrepareStatementHandler;
import com.mini.mybatis.mybatisministep06.executor.statement.StatementHandler;
import com.mini.mybatis.mybatisministep06.mapping.BoundSql;
import com.mini.mybatis.mybatisministep06.mapping.Environment;
import com.mini.mybatis.mybatisministep06.mapping.MappedStatement;
import com.mini.mybatis.mybatisministep06.sqlsession.ResultHandler;
import com.mini.mybatis.mybatisministep06.sqlsession.SqlSession;
import com.mini.mybatis.mybatisministep06.transaction.Transaction;
import com.mini.mybatis.mybatisministep06.transaction.jdbc.JdbcTransactionFactory;
import com.mini.mybatis.mybatisministep06.type.TypeAliasRegistry;

import java.util.HashMap;
import java.util.Map;

/**
 * MyBatis底层全局配置
 */
public class Configuration {

    // 映射注册器
    protected MapperRegistry mapperRegistry = new MapperRegistry(this);

    // 映射语句
    protected Map<String, MappedStatement> mappedStatements = new HashMap<>();

    // 环境
    protected Environment environment;

    // 别名注册器
    protected TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();

    public Configuration() {
        typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
        typeAliasRegistry.registerAlias("DRUID", DruidDataSourceFactory.class);
        typeAliasRegistry.registerAlias("UNPOOLED", UnPooledDataSourceFactory.class);
        typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
    }

    public <T> void addMapper(Class<T> type){
        this.mapperRegistry.addMapper(type);
    }

    public void addMappers(String packName){
        this.mapperRegistry.addMappers(packName);
    }

    public <T> T getMapper(Class<T> type, SqlSession sqlSession){
        return this.mapperRegistry.getMapper(type,sqlSession);
    }

    public <T> boolean hasMapper(Class<T> type){
        return this.mapperRegistry.hasMapper(type);
    }

    public void addMappedStatement(MappedStatement ms){
        this.mappedStatements.put(ms.getId(),ms);
    }

    public MappedStatement getMapStatement(String id){
        return this.mappedStatements.get(id);
    }

    public Environment getEnvironment() {
        return environment;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public TypeAliasRegistry getTypeAliasRegistry() {
        return typeAliasRegistry;
    }

    public void setTypeAliasRegistry(TypeAliasRegistry typeAliasRegistry) {
        this.typeAliasRegistry = typeAliasRegistry;
    }

    /**
     * 创建结果集处理器
     */
    public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, BoundSql boundSql) {
        return new DefaultResultSetHandler(executor, mappedStatement, boundSql);
    }


    /**
     * 创建执行器
     */
    public Executor newExecutor(Transaction tx){
        return new SimpleExecutor(this,tx);
    }

    /**
     * 创建语句处理器
     */
    public StatementHandler newStatementHandler(Executor executor, MappedStatement ms, Object parameter, ResultHandler resultHandler, BoundSql boundSql){
        return new PrepareStatementHandler(executor,ms,parameter,resultHandler,boundSql);
    }

}
